package com.example.utils;

import java.math.BigInteger;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;

import org.apache.commons.codec.digest.DigestUtils;

import sun.misc.BASE64Decoder;

public class MD5Util {

	// md5加密
	public static String md5(String src) {
		return DigestUtils.md5Hex(src);
	}

	// 密码加盐处理
	public static final String salt = "itbooking.123sk";

	public static String inputPassToFormPass(String inputPass) {
		// 混淆视听 slat
		String str = "" + salt.charAt(0) + salt.charAt(2) + inputPass + salt.charAt(5) + salt.charAt(4);
		// 加密一次
		return md5(str);
	}

	// inputPassToFormPass + formPassToDBPass = inputPassToDbPass(数据的最终密码)
	public static String inputPassToDbPass(String inputPass, String saltDB) {
		String formPass = inputPassToFormPass(inputPass);// 11dad9c3d844b8f7eac85c9e4e6de267
		String dbPass = formPassToDBPass(formPass, saltDB);// 把混淆加密的密码在进行一次加密
		return dbPass;
	}

	/**
	 * 
	 * @param formPass
	 * @param salt
	 * @return
	 */
	public static String formPassToDBPass(String formPass, String salt) {
		String str = "" + salt.charAt(0) + salt.charAt(2) + formPass + salt.charAt(5) + salt.charAt(4);
		return md5(str);
	}

	// DES
	private static Key key;
	private static String KEY_STR = "FlyCatZly";
	static {
		try {
			KeyGenerator generator = KeyGenerator.getInstance("DES");
			generator.init(new SecureRandom(KEY_STR.getBytes()));
			key = generator.generateKey();
			generator = null;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 生成32位md5码
	 * 
	 * @param password
	 * @return
	 */
	public static String md5Codes32Bit(String password) {
		try {
			// 得到一个信息摘要器
			MessageDigest digest = MessageDigest.getInstance("md5");
			byte[] result = digest.digest(password.getBytes());
			StringBuffer buffer = new StringBuffer();
			// 把每一个byte 做一个与运算 0xff;
			for (byte b : result) {
				// 与运算
				int number = b & 0xff; // 加盐
				String str = Integer.toHexString(number);
				if (str.length() == 1) {
					buffer.append("0");
				}
				buffer.append(str);
			}

			// 标准的md5加密后的结果
			return buffer.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return "";
		}

	}

	/**
	 * 对字符串md5加密(小写+字母)
	 *
	 * @param str 传入要加密的字符串
	 * @return MD5加密后的字符串
	 */
	public static String getMD5LowerCase(String str) {
		try {
			// 生成一个MD5加密计算摘要
			MessageDigest md = MessageDigest.getInstance("MD5");
			// 计算md5函数
			md.update(str.getBytes());
			// digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
			// BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
			return new BigInteger(1, md.digest()).toString(16);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 对字符串md5加密(大写+数字)
	 *
	 * @param str 传入要加密的字符串
	 * @return MD5加密后的字符串
	 */

	public static String getMD5CapitalsNum(String s) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

		try {
			byte[] btInput = s.getBytes();
			// 获得MD5摘要算法的 MessageDigest 对象
			MessageDigest mdInst = MessageDigest.getInstance("MD5");
			// 使用指定的字节更新摘要
			mdInst.update(btInput);
			// 获得密文
			byte[] md = mdInst.digest();
			// 把密文转换成十六进制的字符串形式
			int j = md.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 对str进行DES解密
	 * 
	 * @param str
	 * @return
	 */
	public static String getDecryptString(String str) {
		BASE64Decoder base64De = new BASE64Decoder();
		try {
			byte[] strBytes = base64De.decodeBuffer(str);
			Cipher cipher = Cipher.getInstance("DES");
			cipher.init(Cipher.DECRYPT_MODE, key);
			byte[] decryptStrBytes = cipher.doFinal(strBytes);
			return new String(decryptStrBytes, "UTF8");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	/**
	 * 凯德加密 方法名： encryption <BR>
	 * 创建人： Flycat <BR>
	 * 时间： 2015年11月14日-下午3:50:43 <BR>
	 * 
	 * @param str 传入要加密的字符串
	 * @param k   加密位数
	 * @return String <BR>
	 * @since 1.0.0
	 */
	public static String encryption(String str, int k) {
		String string = "";
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (c >= 'a' && c <= 'z') {
				c += k % 26;
				if (c < 'a') {
					c += 26;
				}
				if (c > 'z') {
					c -= 26;
				}
			} else if (c >= 'A' && c <= 'Z') {
				c += k % 26;
				if (c < 'A') {
					c += 26;
				}
				if (c > 'Z') {
					c -= 26;
				}
			}
			string += c;
		}
		return string;
	}

	/**
	 * 凯德解密 方法名： dencryption <BR>
	 * 创建人： Flycat <BR>
	 * 时间： 2015年11月14日-下午3:51:46 <BR>
	 * 
	 * @param str 传入加密后的字符串
	 * @param n   要与加密位数一致
	 * @return String <BR>
	 * @since 1.0.0
	 */
	public static String dencryption(String str, int n) {
		String string = "";
		int k = Integer.parseInt("-" + n);
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (c >= 'a' && c <= 'z') {
				c += k % 26;
				if (c < 'a') {
					c += 26;
				}
				if (c > 'z') {
					c -= 26;
				}
			} else if (c >= 'A' && c <= 'Z') {
				c += k % 26;
				if (c < 'A') {
					c += 26;
				}
				if (c > 'Z') {
					c -= 26;
				}
			}
			string += c;
		}
		return string;
	}

	public static void main(String[] args) {
		System.out.println(md5(salt + "123456"));
		System.out.println(inputPassToFormPass("123456"));// 11dad9c3d844b8f7eac85c9e4e6de267
//		System.out.println(formPassToDBPass(inputPassToFormPass("123456"), "1a2b3c4d"));
		System.out.println(inputPassToDbPass("mkxiaoer1986", salt));// b7797cce01b4b131b433b6acf4add449

		System.out.println("MD5 加密 ： " + md5Codes32Bit("admin"));
		System.out.println("MD5 加密 ： " + md5Codes32Bit("zly"));
		System.out.println("MD5 加密 ： " + md5Codes32Bit("zcp"));

		System.out.println("MD5 加密小写字母+数字： " + getMD5LowerCase("admin"));
		System.out.println("MD5 加密小写字母+数字： " + getMD5LowerCase("zly"));
		System.out.println("MD5 加密小写字母+数字： " + getMD5LowerCase("zcp"));

		System.out.println("MD5 加密大写字母+数字 ： " + getMD5CapitalsNum("admin"));
		System.out.println("MD5 加密大写字母+数字 ： " + getMD5CapitalsNum("zly"));
		System.out.println("MD5 加密大写字母+数字 ： " + getMD5CapitalsNum("zcp"));

		System.out.println("凯德加密后:" + encryption(md5Codes32Bit("admin"), 4));
		System.out.println("凯德加密后:" + encryption(md5Codes32Bit("zly"), 4));
		System.out.println("凯德加密后:" + encryption(md5Codes32Bit("zcp"), 4));

		System.out.println("凯德解密后:" + dencryption(encryption(md5Codes32Bit("admin"), 4), 4));
		System.out.println("凯德解密后:" + dencryption(encryption(md5Codes32Bit("zly"), 4), 4));
		System.out.println("凯德解密后:" + dencryption(encryption(md5Codes32Bit("zcp"), 4), 4));

		// 24.凯德加密
		/*
		 * String e = encryption("acxsdfSDFSD584SDF.mp4", 4);
		 * System.out.println("凯德加密后:"+e); String c = dencryption(e, 4);
		 * System.out.println("凯德解密后:"+c);
		 */

		// 26.MD5 加密
//				System.out.println("MD5 加密 ： "+md5Base64("flycat i love you"));

		System.out.println("凯德加密后:" + encryption("TESH100003", 24));
		System.out.println("凯德解密后:" + dencryption(encryption("TESH100003", 24), 24));

	}
}
